add_custom_target(examples)

if(ZENOHCXX_ZENOHC)
	add_custom_target(examples_zenohc)
	add_dependencies(examples examples_zenohc)
endif()

if(ZENOHCXX_ZENOHPICO)
	add_custom_target(examples_zenohpico)
	add_dependencies(examples examples_zenohpico)
endif()

function(add_protobuf target mode)
	if(ZENOHCXX_EXAMPLES_PROTOBUF)
		find_package(Protobuf)
		if(Protobuf_FOUND)
			message(STATUS "Found Protobuf ${protobuf_VERSION}, will build Protobuf example!")

			protobuf_generate_cpp(pb_src pb_hdr ${CMAKE_CURRENT_LIST_DIR}/universal/proto/entity.proto)

			add_library(example_message_${mode} ${pb_hdr} ${pb_src})
			target_include_directories(example_message_${mode} INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
			target_link_libraries(example_message_${mode} PUBLIC protobuf::libprotobuf)

			target_link_libraries(${target} PRIVATE example_message_${mode})
			target_compile_definitions(${target} PRIVATE -DZENOH_CPP_EXAMPLE_WITH_PROTOBUF)
		else()
			message("Protobuf not found, will build without Protobuf example!")
		endif()
	endif()
endfunction()

function(add_example file mode lib)
	get_filename_component(filename ${file} NAME_WE)
	set(target ${filename}_${mode})
	add_executable(${target} EXCLUDE_FROM_ALL ${file})
	set_target_properties(${target} PROPERTIES 
		OUTPUT_NAME ${filename}
		RUNTIME_OUTPUT_DIRECTORY ${mode})
	add_dependencies(examples_${mode} ${target})
	add_dependencies(${target} ${lib})
    target_link_libraries(${target} PUBLIC ${lib})
	if("${target}" MATCHES "z_bytes_*")
		add_protobuf(${target} ${mode})
	endif()
	copy_dlls(${target})
endfunction()

function(add_examples glob mode lib)
	file(GLOB files ${glob})
	foreach(file ${files})
		# Exclude SHM examples if SHM feature is disabled
		if(NOT(ZENOHC_BUILD_WITH_SHARED_MEMORY AND (ZENOHC_BUILD_WITH_UNSTABLE_API)))
			if(${file} MATCHES "^.*_shm.*$")
				continue()
			endif()
		endif()

		if(NOT(ZENOHC_BUILD_WITH_UNSTABLE_API))
			if(${file} MATCHES ".*liveliness.*$")
				continue()
			endif()
		endif()

		if(("${mode}" STREQUAL "zenohc") AND (NOT(ZENOHC_BUILD_WITH_UNSTABLE_API)))
			if(${file} MATCHES ".*liveliness.*$")
				continue()
			endif()
			if(${file} MATCHES ".*querier.*$")
				continue()
			endif()
			if(${file} MATCHES ".*query_sub.*$")
				continue()
			endif()
			if(${file} MATCHES ".*pub_cache.*$")
				continue()
			endif()
		endif()
		if("${mode}" STREQUAL "zenohpico")
			if (((${file} MATCHES "^.*pub.*$") OR (${file} MATCHES "^.*delete.*$") OR (${file} MATCHES "^.*put.*$")
				OR (${file} MATCHES "^.*ping.*$") OR (${file} MATCHES "^.*pong.*$")) 
				AND NOT(ZENOHPICO_FEATURE_PUBLICATION)
			)
				continue()
			endif()
			if (((${file} MATCHES "^.*sub.*$") OR (${file} MATCHES "^.*ping.*$") OR (${file} MATCHES "^.*pong.*$")) 
				AND NOT(ZENOHPICO_FEATURE_SUBSCRIPTION)
			)
				continue()
			endif()
			if ((${file} MATCHES "^.*get.*$") AND NOT(ZENOHPICO_FEATURE_QUERY))
				continue()
			endif()
			if ((${file} MATCHES "^.*queryable.*$") AND NOT(ZENOHPICO_FEATURE_QUERYABLE))
				continue()
			endif()
			if ((${file} MATCHES "^.*liveliness.*$") AND NOT(ZENOHPICO_FEATURE_LIVELINESS))
				continue()
			endif()
		endif()

		add_example(${file} ${mode} ${lib})
	endforeach()
endfunction()

if(ZENOHCXX_ZENOHC)
	# zenohcxx examples compiled with C++ compiler with zenohc
	add_examples("${CMAKE_CURRENT_SOURCE_DIR}/zenohc/*.cxx" zenohc zenohcxx::zenohc)
	add_examples("${CMAKE_CURRENT_SOURCE_DIR}/universal/*.cxx" zenohc zenohcxx::zenohc)
endif()
if(ZENOHCXX_ZENOHPICO)
	# zenohcxx examples compiled with C++ compiler with zenohpico
	add_examples("${CMAKE_CURRENT_SOURCE_DIR}/universal/*.cxx" zenohpico zenohcxx::zenohpico)
endif()

# check compilation of simple examples
#add_examples("${CMAKE_CURRENT_SOURCE_DIR}/simple/universal/z_simple.cxx" zenohpico zenohcxx::zenohpico)
#add_examples("${CMAKE_CURRENT_SOURCE_DIR}/simple/universal/z_simple.cxx" zenohc zenohcxx::zenohc::lib)
#add_examples("${CMAKE_CURRENT_SOURCE_DIR}/simple/zenohpico/zp_simple.cxx" zenohpico zenohcxx::zenohpico)
#add_examples("${CMAKE_CURRENT_SOURCE_DIR}/simple/zenohc/zc_simple.cxx" zenohc zenohcxx::zenohc::lib)
